﻿using BiliBiliLiveDanMuTool.Properties;
using BiliBiliLiveDanMuTool.Utils;
using DanMuUI;
using LibPlug.Model;
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;

namespace BiliBiliLiveDanMuTool.UI
{
    public partial class UI_Main : Form
    {
        private DanMuClient.DanMuClient m_client;
        private NotifyIcon m_notifyIcon;
        private MainWindow m_overlay;

        private const int WS_EX_TRANSPARENT = 0x20;
        private const int GWL_EXSTYLE = -20;

        public UI_Main()
        {
            InitializeComponent();
        }

        #region > 各种UI事件 <
        private void UI_Main_Load(object sender, EventArgs e)
        {
            initUIResource();
            loadPlugins();
        }

        private void button_ConnectRoom_Click(object sender, EventArgs e)
        {
            m_client = new DanMuClient.DanMuClient()
            {
                PeopleNumber = showInfo,
                DanMu = appendDanMu
            };

            if (!m_client.Connected)
            {
                string _url = textBox_LiveRoomUrl.Text;
                if (!_url.Contains(@"http://")) _url = @"http://" + _url;
                m_client.ConnectBilibili(_url);
                button_ConnectRoom.Enabled = false;
                button_DisConnect.Enabled = true;
            }
        }

        private void button_DisConnect_Click(object sender, EventArgs e)
        {
            if (m_client != null)
            {
                m_client.DisConnect();
                this.Text = "Bilibili直播弹幕助手";
                button_ConnectRoom.Enabled = true;
                button_DisConnect.Enabled = false;
            }
        }

        private void UI_Main_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (m_client != null) m_client.DisConnect();
            m_notifyIcon.Visible = false;
            Environment.Exit(0);
        }

        private void UI_Main_SizeChanged(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                this.ShowInTaskbar = false;
                m_notifyIcon.Visible = true;
            }
        }
        private void checkBox_IsOpenWindow_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_IsOpenWindow.Checked) m_overlay.Show();
            else m_overlay.Hide();
            Activate();
        }
        #endregion

        /// <summary>
        /// 显示在线人数
        /// </summary>
        /// <param name="message">消息</param>
        private void showInfo(string message)
        {
            this.Text = "Bilibili直播弹幕助手 当前在线：" + message + "人";
        }

        /// <summary>
        /// 弹幕操作
        /// </summary>
        /// <param name="model"></param>
        private void appendDanMu(DanMuMessageModel model)
        {
            if(model != null)
            {
                textBox_Logbox.AppendText(string.Format("{0}：{1}\r\n", model.User, model.Content));
                switch (model.Type)
                {
                    case MessageType.Normal:
                        addDM(model.User, model.Content,Brushes.Yellow);
                        break;
                    case MessageType.WelCome:
                        addDM(model.User, model.Content, Brushes.Red);
                        break;
                    case MessageType.Gift:
                        addDM(model.User, model.Content, Brushes.Orange);
                        break;
                }
            }
        }

        /// <summary>
        /// 初始化UI资源
        /// </summary>
        private void initUIResource()
        {
            CheckForIllegalCrossThreadCalls = false;
            #region > 托盘图标操作 <
            m_notifyIcon = new NotifyIcon();
            m_notifyIcon.Text = "哔哩哔哩直播助手";
            m_notifyIcon.DoubleClick += (object sender, EventArgs e) =>
            {
                if (this.WindowState == FormWindowState.Minimized)
                {
                    this.ShowInTaskbar = true;
                    this.Activate();
                    this.WindowState = FormWindowState.Normal;
                    m_notifyIcon.Visible = false;
                }
            };
            this.Icon = m_notifyIcon.Icon = Resources.icon;
            #endregion
            openOverlay();
        }

        /// <summary>
        /// 加载插件
        /// </summary>
        private void loadPlugins()
        {
            GlobalMember.DanMuPluginsManager.LoadPlugins();
            fillPlugins();
        }

        /// <summary>
        /// 填充插件列表框
        /// </summary>
        /// <returns></returns>
        private Task<int> fillPlugins()
        {
            var _task = Task.Run(() =>
            {
                int _count = 0;
                foreach (var item in GlobalMember.DanMuPluginsManager.Plugins)
                {
                    listView_PluginsList.Items.Add(new ListViewItem(new string[]
                    {
                        item.Info.PlugName,
                        item.Info.PlugAuthor,
                        item.Info.PlugDescript,
                        item.Info.PlugVersion.ToString()
                    }));
                    item.Init(null);
                    _count++;
                }
                return _count;
            });
            return _task;
        }

        /// <summary>
        /// 打开侧边栏
        /// </summary>
        private void openOverlay()
        {
            m_overlay = new MainWindow();
            m_overlay.Deactivated += (object sender,EventArgs e) => 
            {
                if(sender is MainWindow)
                {
                    (sender as MainWindow).Topmost = true;
                }
            };
            m_overlay.SourceInitialized += delegate
            {
                var hwnd = new WindowInteropHelper(m_overlay).Handle;
                var extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
                SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);
            };
            m_overlay.Background = Brushes.Transparent;
            m_overlay.ShowInTaskbar = false;
            m_overlay.Topmost = true;
            m_overlay.Top = SystemParameters.WorkArea.Top + DanMuSettingValue.MainOverlayYoffset -300;
            m_overlay.Left = SystemParameters.WorkArea.Right - DanMuSettingValue.MainOverlayWidth + DanMuSettingValue.MainOverlayXoffset;
            m_overlay.Height = SystemParameters.WorkArea.Height;
            m_overlay.Width = DanMuSettingValue.MainOverlayWidth;
            m_overlay.Show();
        }

        /// <summary>
        /// 侧边栏数据添加
        /// </summary>
        /// <param name="user">用户名</param>
        /// <param name="text">弹幕文本</param>
        /// <param name="warn">是否着重标注</param>
        /// <param name="foreceenablefullscreen"></param>
        private void addDM(string user, string text, Brush userNameColor, bool foreceenablefullscreen = false)
        {
            if(m_overlay.Dispatcher.CheckAccess())
            {
                var c = new DanMuTextControl();
                c.UserName.Text = user;
                c.UserName.Foreground = userNameColor;
                c.Text.Text = text;
                c.ChangeHeight();
                var sb = (Storyboard)c.Resources["Storyboard1"];
                sb.Completed += (object sender, EventArgs e) =>
                {
                    var s = sender as ClockGroup;
                    if (s == null) return;
                    var dm = Storyboard.GetTarget(s.Children[2].Timeline) as DanMuTextControl;
                    if (dm != null)
                    {
                        m_overlay.LayoutRoot.Children.Remove(dm);
                    }
                };

                m_overlay.LayoutRoot.Children.Add(c);
            }else
            {
                m_overlay.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => addDM(user, text,userNameColor)));
            }
        }

        #region > 非托管DLL <
        [DllImport("user32", EntryPoint = "SetWindowLong")]
        private static extern uint SetWindowLong(IntPtr hwnd, int nIndex, uint dwNewLong);

        [DllImport("user32", EntryPoint = "GetWindowLong")]
        private static extern uint GetWindowLong(IntPtr hwnd, int nIndex);
        #endregion
    }
}
